#pragma once
#include "Common.hpp"
#include "Mutex.hpp"

namespace SocketModule
{
    const int default_pending_num = 10;
    class TCPConnectSocket;
    class Socket
    {
    protected:
        int _sockfd;
        InetAddr _addr;
        MutexModule::Mutex _mutex;  // 线程安全锁

        // 基础套接字创建（供子类调用）
        void CreateSocket(int type)
        {
            _sockfd = ::socket(AF_INET, type, 0);
            if(_sockfd == -1)
            {
                LOG(LogLevel::FATAL) << "socket: 申请套接字失败! " << strerror(errno);
                throw std::runtime_error("socket create failed");  // 抛异常而非直接退出
            }
        }

        // 模板方法的核心步骤（纯虚函数，由子类实现）
        virtual void CreateSocket() = 0;
        virtual void Bind() = 0;
        virtual void Listen() = 0;
        virtual void Connect() = 0;

        // 模板方法：固定初始化流程（禁止子类重写）
        virtual void Initialize() final
        {
            CreateSocket();
            Bind();
            Listen();
            Connect();
        }

    public:
        // 用于服务端/客户端套接字（未连接状态）
        Socket(const std::string& ip, in_port_t port) 
            : _sockfd(-1)
            , _addr(ip, port)
        {}

        // 用于已连接套接字（如accept返回的TCP连接）
        Socket(const int sockfd, const InetAddr& addr)
            : _sockfd(sockfd)
            , _addr(addr)
        {}

        void Close()
        {
            if(_sockfd != -1)
                ::close(_sockfd);
            _sockfd = -1;
        }

        // 虚析构函数确保子类资源正确释放
        virtual ~Socket()
        {
            Close();
        }

        const InetAddr& Addr() const { return _addr; }
        const int& SockFd() const { return _sockfd; }
        // 纯虚函数：定义子类必须实现的接口
        virtual std::shared_ptr<TCPConnectSocket> Accept() = 0;
        // TCP协议不考虑第二个参数
        virtual int Receive(std::string& recv_msg, InetAddr* peer = nullptr) = 0;
        virtual int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) = 0;
    };

    // TCP连接套接字（由accept返回）
    class TCPConnectSocket : public Socket
    {
    public:
        TCPConnectSocket(int sockfd, const InetAddr& addr)
            : Socket(sockfd, addr)  // 直接使用已创建的套接字
        {
            Initialize();
        }

        // 重写基类方法（已连接套接字无需重新创建）
        void CreateSocket() override {}

        int Receive(std::string& recv_msg, InetAddr* peer = nullptr) override
        {
            MutexModule::LockGuard lock(_mutex);
            char buffer[BUFFER_SIZE];
            ssize_t size = ::recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if (size <= 0)
            {
                recv_msg.clear();
                if (size < 0 && errno != EAGAIN && errno != EWOULDBLOCK)
                    LOG(LogLevel::ERROR) << "recv error: " << strerror(errno);
                return size;
            }
            buffer[size] = '\0';
            recv_msg = buffer;
            return size;
        }

        int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) override
        {
            MutexModule::LockGuard lock(_mutex);
            ssize_t size = ::send(_sockfd, send_msg.c_str(), send_msg.size(), 0);
            if (size == -1)
                LOG(LogLevel::ERROR) << "send error: " << strerror(errno);
            return size;
        }

    protected:  // 修正访问权限
        void Bind() override {}  // 已连接套接字无需绑定
        void Listen() override {}  // 已连接套接字无需监听
        void Connect() override {}  // 已连接套接字无需再次连接

        std::shared_ptr<TCPConnectSocket> Accept() override
        {
            return nullptr;  // 连接套接字不处理accept
        }
    };

    // TCP监听套接字
    class TCPListenSocket : public Socket
    {
    public:
        TCPListenSocket(in_port_t port)
            : Socket("0.0.0.0", port)  // 监听所有网卡
        {
            Initialize();
        }

        // 重写基类方法（显式标记override）
        void CreateSocket() override
        {
            Socket::CreateSocket(SOCK_STREAM);  // TCP类型
        }

        std::shared_ptr<TCPConnectSocket> Accept() override
        {
            MutexModule::LockGuard lock(_mutex);  // 线程安全保护
            InetAddr client;
            int sockfd = ::accept(_sockfd, client.NetAddrPtr(), &client.AddrLen());
            client = InetAddr(client.NetAddr());
            if(sockfd == -1)
            {
                if(errno != EAGAIN && errno != EWOULDBLOCK)
                    LOG(LogLevel::WARNING) << "accept: 建立连接失败! " << strerror(errno);
                return nullptr;
            }
            LOG(LogLevel::INFO) << "accept: 建立连接成功! [" << client.Info() << "]";
            return std::make_shared<TCPConnectSocket>(sockfd, client);
        }

    protected: 
        void Bind() override
        {
            int n = ::bind(_sockfd, _addr.NetAddrPtr(), _addr.AddrLen());
            if(n == -1)
            {
                LOG(LogLevel::FATAL) << "bind: 绑定地址信息失败! " << strerror(errno);
                throw std::runtime_error("bind failed");
            }
        }

        void Listen() override
        {
            int n = ::listen(_sockfd, default_pending_num);
            if(n == -1)
            {
                LOG(LogLevel::FATAL) << "listen: 设置监听套接字失败! " << strerror(errno);
                throw std::runtime_error("listen failed");
            }
        }

        void Connect() override  // TCP监听套接字无需主动连接
        {}
        int Receive(std::string& recv_msg, InetAddr* peer = nullptr) override
        {
            return -1;  // 监听套接字不处理接收
        }
        int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) override
        {
            return -1;  // 监听套接字不处理发送
        }
    };

    // TCP客户端套接字
    class TCPClientSocket : public Socket
    {
    public:
        TCPClientSocket(const std::string& ip, in_port_t port)
            : Socket(ip, port)
        {
            Initialize();
        }

        void CreateSocket() override
        {
            Socket::CreateSocket(SOCK_STREAM);  // TCP类型
        }

        void Connect() override
        {
            int n = ::connect(_sockfd, _addr.NetAddrPtr(), _addr.AddrLen());
            if(n == -1)
            {
                LOG(LogLevel::FATAL) << "connect: 连接失败! " << strerror(errno);
                throw std::runtime_error("connect failed");
            }
            LOG(LogLevel::INFO) << "客户端套接字已连接到[" << _addr.Info() << "]";
        }

        int Receive(std::string& recv_msg, InetAddr* peer = nullptr) override
        {
            MutexModule::LockGuard lock(_mutex);
            char buffer[BUFFER_SIZE];
            ssize_t size = ::recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if (size <= 0)
            {
                recv_msg.clear();
                if (size < 0)
                    LOG(LogLevel::ERROR) << "recv error: " << strerror(errno);
                return size;
            }
            buffer[size] = '\0';
            recv_msg = buffer;
            return size;
        }

        int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) override
        {
            MutexModule::LockGuard lock(_mutex);
            ssize_t size = ::send(_sockfd, send_msg.c_str(), send_msg.size(), 0);
            if (size == -1)
                LOG(LogLevel::ERROR) << "send error: " << strerror(errno);
            return size;
        }

    protected:  // 修正访问权限
        void Bind() override {}  // 客户端通常不主动绑定
        void Listen() override {}  // 客户端无需监听

        std::shared_ptr<TCPConnectSocket> Accept() override
        {
            return nullptr;  // 客户端不处理accept
        }
    };

    // UDP服务端套接字
    class UDPServerSocket : public Socket
    {
    public:
        UDPServerSocket(const std::string& ip, in_port_t port)
            : Socket(ip, port)
        {
            Initialize();
        }

        void CreateSocket() override
        {
            Socket::CreateSocket(SOCK_DGRAM);  // UDP类型
        }

        int Receive(std::string& recv_msg, InetAddr* peer = nullptr) override
        {
            MutexModule::LockGuard lock(_mutex);
            char buffer[BUFFER_SIZE];
            ssize_t size = ::recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, 
                                     peer->NetAddrPtr(), &peer->AddrLen());
            *peer = InetAddr(peer->NetAddr());
            if (size <= 0)
            {
                recv_msg.clear();
                if (size < 0)
                    LOG(LogLevel::ERROR) << "recvfrom error: " << strerror(errno);
                return size;
            }
            buffer[size] = '\0';
            recv_msg = buffer;
            return size;
        }

        int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) override
        {
            MutexModule::LockGuard lock(_mutex);
            if (peer.Ip().empty())  // 确保目标地址有效
            {
                LOG(LogLevel::ERROR) << "sendto error: 目标地址为空";
                return -1;
            }
            ssize_t size = ::sendto(_sockfd, send_msg.c_str(), send_msg.size(), 0,
                                   peer.NetAddrPtr(), peer.AddrLen());
            if (size == -1)
                LOG(LogLevel::ERROR) << "sendto error: " << strerror(errno);
            return size;
        }

    protected:  // 修正访问权限并添加override
        void Bind() override
        {
            int n = ::bind(_sockfd, _addr.NetAddrPtr(), _addr.AddrLen());
            if(n == -1)
            {
                LOG(LogLevel::FATAL) << "bind: 绑定地址信息失败! " << strerror(errno);
                throw std::runtime_error("bind failed");
            }
        }

        void Listen() override {}  // UDP无需监听
        void Connect() override {}  // UDP服务端无需主动连接

        std::shared_ptr<TCPConnectSocket> Accept() override
        {
            return nullptr;  // UDP不支持accept
        }
    };

    // UDP客户端套接字
    class UDPClientSocket : public Socket
    {
    public:
        UDPClientSocket(const std::string& ip, in_port_t port)
            : Socket(ip, port)
        {
            Initialize();
        }

        void CreateSocket() override
        {
            Socket::CreateSocket(SOCK_DGRAM);  // UDP类型
        }

        int Receive(std::string& recv_msg, InetAddr* peer = nullptr) override
        {
            MutexModule::LockGuard lock(_mutex);
            char buffer[BUFFER_SIZE];
            ssize_t size = ::recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, 
                                     peer->NetAddrPtr(), &peer->AddrLen());
            *peer = InetAddr(peer->NetAddr());
            if (size <= 0)
            {
                recv_msg.clear();
                if (size < 0)
                    LOG(LogLevel::ERROR) << "recvfrom error: " << strerror(errno);
                return size;
            }
            buffer[size] = '\0';
            recv_msg = buffer;
            return size;
        }

        int Send(const std::string& send_msg, const InetAddr& peer = InetAddr()) override
        {
            MutexModule::LockGuard lock(_mutex);
            InetAddr target = peer.Ip().empty() ? _addr : peer;  // 支持默认目标地址
            ssize_t size = ::sendto(_sockfd, send_msg.c_str(), send_msg.size(), 0,
                                   target.NetAddrPtr(), target.AddrLen());
            if (size == -1)
                LOG(LogLevel::ERROR) << "sendto error: " << strerror(errno);
            return size;
        }

    protected:  // 修正访问权限并添加override
        void Bind() override {}  // UDP客户端通常不绑定
        void Listen() override {}  // UDP无需监听
        void Connect() override {}  // UDP无需连接

        std::shared_ptr<TCPConnectSocket> Accept() override
        {
            return nullptr;  // UDP不支持accept
        }
    };
}